using System;
using System.Reflection;
using System.Reflection.Emit;

/*************** TODO TODO TODO
 * fuera Word.cs
 * Dictionary.cs implementarlo todo usando Memory y tirando de indices a Memory
 */

namespace NForth3
{
    class NForth
    {
        private AssemblyBuilder assembly_builder;
        private Memory memory;
        private Stack ds;
        private Stack rs;
        private Word word;
        private Dictionary dictionary;
        private Compiler compiler;

        public AssemblyBuilder Assembly { get { return assembly_builder; } }
        public Memory Memory { get { return memory; } }
        public Stack DS { get { return ds; } }
        public Stack RS { get { return rs; } }
        public Word Word { get { return word; } }
        public Dictionary Dictionary { get { return dictionary; } }
        public Compiler Compiler { get { return compiler; } }

        public NForth()
        {
            AssemblyName assembly = new AssemblyName("NForthAssembly");
            assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.RunAndSave);

            memory = new Memory(this);
            ds = new Stack(this, "DataStack");
            rs = new Stack(this, "ReturnStack");
            word = new Word(this);
            dictionary = new Dictionary(this);
            compiler = new Compiler(this);
			
            dictionary.Add("line", 0, typeof(NextLine));
            dictionary.Add("word", 0, typeof(NextWord));
        }

        public void Create(string word)
        {
            // TODO compiler.Invoke Create
        }

        public void Finish()
        {
            // TODO
            // type = compiler.Invoke Finish
            // dictionary.Add word, 0, type
        }

        public void Execute(string word)
        {
            // TODO
            // type = dictionary.Find word
            // type.GetMethod("Execute").Invoke
        }

        public void Include(string filename)
        {
            // TODO
        }

        public void Interpret()
        {
        	while(true)
        	{
        		NextWord.Execute();
        		Console.WriteLine("WORD: " + NextWord.Value);
        	}
            // TODO
            // while(true) {
            // word = parser.Invoke Word
            // if(method(word))
            //   if(state == 0 || immediate(word))
            //     Execute(method(word))
            //   else
            //     Compile(method(word))
            // else if(field(word))
            //   if(state == 0)
            //     DataStack.Push(field(word))
            //   else
            //     Compile(field(word))
            // else {
            //   if(state == 0)
            //     DataStack.Push(int.Parse(word))
            //   else
            //     Compile(int.Parse(word))
            // }
            // }
        }
    }
}
